//#############################################################################
//#############################################################################
//This source file was written by Mert Dogar. If you have some questions about 
//the source code, please do not hesitate to ask me.
//The code is under GPL.
//Email: mertdogar@gmail.com , http://code.google.com/p/electron-cds
//#############################################################################
//#############################################################################


#include "component_base.h"
//class deffs



//#############################################################################
//Constructor
//#############################################################################
cbase::cbase(std::string ctype,std::string cname, vector2 pos, e_angle my_angle)
{
	sroot = tovector2 (0,0);
	position=pos;
	type=ctype;	name=cname;
	angle = my_angle;
	load_shm (ctype);
	
}
//constructor for line
cbase::cbase(vector2 start, vector2 end, float line_width, rgbcolor pcolor)
{
	sroot = tovector2 (0,0);
	position=start;
	positionend=end;
	type="wire";
	shape tmp;
	tmp.type ="wire";
	tmp.color = pcolor;
	tmp.c1 =start;
	tmp.c2 =end;
	shm.push_back(tmp);

}
//#############################################################################
//End of Constructor
//#############################################################################




//#############################################################################
//Helper Scale Functions
//#############################################################################
float cbase::coscale(float rhs, float factor)
{	
	return rhs/factor;
	
}

float cbase::scale(float rhs, float factor)
{	
	return rhs*factor;
	
}

//#############################################################################
//End of Helper Scale Functions
//#############################################################################



//#############################################################################
//Angle to Integer Converters
//#############################################################################
bool cbase::int2bool(int integer)
{
	if(integer==0)
		return false;
	else
		return true;
	
}
int cbase::angle2int(e_angle ang)
{
	if(ang==angle_0)
		return 0;
	else if(ang==angle_90)
		return 1;
	else if(ang==angle_180)
		return 2;
	else if(ang==angle_270)
		return 3;
}
cbase::e_angle cbase::int2angle(int ang)
{
	if(ang==0)
		return angle_0;
	else if(ang==1)
		return angle_90;
	else if(ang==2)
		return angle_180;
	else if(ang==3)
		return angle_270;
	else 
		return angle_0;
}
//#############################################################################
//End of Angle to Integer Converters
//#############################################################################


void cbase::set_angle(int ang)
{

	angle = int2angle(ang);

}
int cbase::get_angle()
{
	return angle2int (angle);
}

int cbase::get_property_size()
{
	std::cout<<  "Returning property list size " << prop.size() << std::endl;
	return prop.size();
}

void cbase::set_property_visible(std::string str,bool val)
{
	for(int i = 0; i < prop.size();i++)
	{
		if(prop[i].name==str)
			prop[i].visible=val;
	}
}
void cbase::set_property_value(std::string str,std::string val)
{
	for(int i = 0; i < prop.size();i++)
	{
		if(prop[i].name==str)
			prop[i].value=val;
	}
}

bool cbase::get_property_visible(std::string str)
{
	for(int i = 0; i < prop.size();i++)
	{
		if(prop[i].name==str)
			return prop[i].visible;
	}
	
	return false;
}

std::string cbase::get_property_value(std::string str)
{
	for(int i = 0; i < prop.size();i++)
	{
		if(prop[i].name==str)
			return prop[i].value;
	}
	
	return str;
}
bool cbase::get_property_visible(int index)
{
	if(index >=0 && index < prop.size())
		return prop[index].visible;
	else
		return false;
}
std::string cbase::get_property_name(int index)
{
	if(index >=0 && index < prop.size())
		return prop[index].name;
	else
		return "-1";
}
void cbase::set_property_name(int index,std::string val)
{
	if(index >=0 && index < prop.size())
		prop[index].value=val;

}

std::string cbase::get_property_value(int index)
{
	if(index >=0 && index < prop.size())
		return prop[index].value;
	else
		return "-1";
}


void cbase::add_port(vector2 pos)
{
	cport tmp(pos);
	ports.push_back(tmp);
	
}



bool cbase::load_shm(std::string cname)
{
	std::ifstream ifs(cname.c_str());
	std::string line, word;
	//the componenet file cannot >> be opened
	if(ifs.fail())
	   return false;
	
	getline(ifs,name);
	getline(ifs,line);
	std::istringstream strs(line);
	strs >> positionend.x >> positionend.y;

	
	while(getline(ifs,line))
	   {
		   shape tmp;
		   std::istringstream istr(line);
		   istr >> word;
		   
		   
		   if(word == "port")
		   {
			 float p1,p2;
			 istr >> p1 >> p2;
		   	 add_port(tovector2 (p1,p2));
		   }
		   else if(word == "text")
		   {
				std::string s1;
				float p1,p2;
				istr >> tmp.text >> tmp.c1.x >> tmp.c1.y >> tmp.color.red >> tmp.color.green >> tmp.color.blue;
				tmp.type="text";
		  		shm.push_back(tmp);
		   }
		   else if(word == "property")
		   {
				property tmp;
			   	int vis;
			    istr >> tmp.name >> tmp.value >> vis;
				tmp.visible = int2bool (vis);
		  		prop.push_back(tmp); 
		   }
		   else if(word == "%")
		   {
			   	//Comment Do nothing
		   }
		   else //line
		   {
		   		std::istringstream istr2(line);
		   		istr2 >> tmp.type >> tmp.c1.x >> tmp.c1.y >> tmp.c2.x >> tmp.c2.y >> tmp.color.red >> tmp.color.green >> tmp.color.blue >> tmp.additional.x >> tmp.additional.y;
		   		shm.push_back(tmp);
		   }
		   
	   }
	ifs.close();
	
	return true;

}

bool cbase::select(Cairo::RefPtr<Cairo::Context> cr, vector2 mpos, rgbcolor mcolor, float factor, vector2 sroot,bool isprint)
{
	if(isonme(mpos))
	{	
	
			draw(cr,mcolor,factor,sroot);
		return true;
	}
	else
	{	
			draw(cr,torgbcolor (-1,-1,-1),factor,sroot);
		return false;
	}
}

//returns if the given vector is on the component
bool cbase::isonme(vector2 cpos)
{	
	if(type=="wire")
	{
		if(cpos.x < (position.x + positionend.x + 5) && cpos.x > (position.x - 5) && cpos.y < (position.y + positionend.y + 5) && cpos.y > (position.y - 5))
			return true;

	}
	else
	{
		if(angle==angle_0)
			if(cpos.x < (position.x + positionend.x + 5) && cpos.x > (position.x - 5) && cpos.y < (position.y + positionend.y + 5) && cpos.y > (position.y - 5))
				return true;
		if(angle==angle_90)
			if(cpos.x < (position.x + positionend.y + 5) && cpos.x > (position.x - 5) && cpos.y < (position.y + positionend.x + 5) && cpos.y > (position.y - 5))
				return true;
	}
	return false;
}


//draws the vectors on the context. 
bool cbase::draw(Cairo::RefPtr<Cairo::Context> cr, rgbcolor clr, float factor, vector2 sroot)
{
	sroot.x=-sroot.x;
	sroot.y=-sroot.y;
	
	for(int i = 0;i<shm.size();i++)
	{
		if(clr.red==-1 && clr.blue==-1 && clr.green==-1)
		{

			cr->set_source_rgb(shm[i].color.red, shm[i].color.green, shm[i].color.blue);
		}
		else
		{

			cr->set_source_rgb(clr.red, clr.green, clr.blue);
		}

		cr->set_line_width(scale(1,factor));			
		if(shm[i].type=="wire")
		{	
			cr->move_to(scale(sroot.x + position.x + shm[i].c1.x,factor),scale(sroot.y + position.y + shm[i].c1.y,factor));
			cr->line_to(scale(sroot.x + position.x + shm[i].c2.x,factor),scale(sroot.y + position.y + shm[i].c2.y,factor));
			
		}
		else if(shm[i].type=="line")
		{
			if(shm[i].additional.x!=0)
				cr->set_line_width(scale(shm[i].additional.x,factor));
			
			if(angle==angle_0)
			{	
				
				cr->move_to(scale(sroot.x + position.x + shm[i].c1.x,factor),scale(sroot.y + position.y + shm[i].c1.y,factor));
				cr->line_to(scale(sroot.x + position.x + shm[i].c2.x,factor),scale(sroot.y + position.y + shm[i].c2.y,factor));
			}
			else if(angle==angle_90)
			{	
				cr->move_to(scale(sroot.x + position.x + shm[i].c1.y,factor),scale(sroot.y + position.y + shm[i].c1.x,factor));
				cr->line_to(scale(sroot.x + position.x + shm[i].c2.y,factor),scale(sroot.y + position.y + shm[i].c2.x,factor));	
			}
		}
		else if(shm[i].type=="circle")
		{
			if(shm[i].c2.y!=0)
				cr->set_line_width(scale(shm[i].c2.y,factor));
			
			if(angle==angle_90)
			{			
				//cr->move_to(scale(sroot.x + position.x + shm[i].c1.y,factor), scale(sroot.y + position.y + shm[i].c1.x,factor));
				cr->arc(scale(sroot.x + position.x + shm[i].c1.y,factor),scale(sroot.y + position.y + shm[i].c1.x,factor), scale(shm[i].c2.x,factor) , shm[i].additional.x, shm[i].additional.y);
			}
			else if(angle==angle_0)
			{			
				//cr->move_to(scale(sroot.x + position.x + shm[i].c1.x,factor), scale(sroot.y + position.y + shm[i].c1.y,factor));
				cr->arc(scale(sroot.x + position.x + shm[i].c1.x,factor),scale(sroot.y + position.y + shm[i].c1.y,factor), scale(shm[i].c2.x,factor) , shm[i].additional.x, shm[i].additional.y);
			}
		}
		else if(shm[i].type=="text")
		{
			cr->set_font_size(12*factor);
			
			if(angle==angle_0)
			{					
			cr->move_to(scale(sroot.x + position.x + shm[i].c1.x,factor),scale(sroot.y + position.y + shm[i].c1.y,factor));
			cr->show_text(get_property_value (shm[i].text));
			}
			else if(angle==angle_90)
			{					

			cr->move_to(scale(sroot.x + position.x + shm[i].c1.x,factor),scale(sroot.y + position.y + shm[i].c1.y,factor));
			cr->show_text(get_property_value (shm[i].text));

			}
		}
		
		cr->stroke();
	}
		
	
	
	vector2 tmp=tovector2 (sroot.x + position.x, sroot.y + position.y);	
	

	
	
	for(int i = 0; i< ports.size(); i++)
	{	
		ports[i].draw(cr, tmp,factor,angle2int(angle));
	}
	    
}



//draws the vectors on the context. 
bool cbase::draw_area(Cairo::RefPtr<Cairo::Context> cr, rgbcolor clr, float factor, vector2 sroot)
{
	sroot.x=-sroot.x;
	sroot.y=-sroot.y;
	cr->set_source_rgb(clr.red,clr.green,clr.blue);
	cr->rectangle(scale(sroot.x + position.x-10,factor),scale(sroot.y + position.y-10,factor),scale(sroot.x + position.x + positionend.x + 10,factor),scale(sroot.y + position.y + positionend.y + 10,factor));
	cr->fill();
}
